Run-Time Type Information (RTTI)


In normal cases the type of any variable can be determined at compile time, for
example if we write this declaration:

var
Count: Integer;

The compiler will know the fact that
Count is of integer type, so that if we try
to assign string to
Count, compile time error will be generated (Type mismatch):

 Count:= 'Hello';

At run time we can not check type of any variable, bacause the type of variable
cann't be changed or used for more than one type.

Object Oriented Programming in Delphi introduces new method of run-time type checking
using
as and is operators. As you might know any object reference can be used to
hold any object of the same type as well as descendant types, for example:

var
MyObject:
TControl;
begin
MyObject:=
Button1;
MyObject:=
Form1;

TControl class is the anscestor class for all Delphi controls such as forms, buttons,
edit boxes and so on, so that we can assign any control to MyObject variable. Look
for
TButton and TForm hierarchy:

TButton hierarchy:

TObject
  |
TPersistent
  |
TComponent
  |
TWinControl
  |
TButtonControl
  |
TButton
 

TForm hierarchy:

TObject
 |
TPersistent
 |
TComponent
 |
TControl
 |
TWinControl
 |
TScrollingWinControl
 |
TCustomForm
 |
TForm

As you have seen, TForm and TButton share TControl anscestor. Another important
fact that the TObject is the parent class for any Delphi class even if you do not
explicity inherit it, for example if you define three class such as:

type
TFirst = Class(
TObject)
.....

TSecond = Class(
TForm)
.....

TThird = Class
...


In above example TFirst declared as a direct descendant of TObject class. TSecond declared
as direct descendant of
TForm, because TForm was inherits TObject class so that TObject
class will be inherited by
TSecond class. TThird class declared without any explicit
anscestor so that Delphi - by default - will assume that
TObject is the anscestor
of
TThird class. The below declarations in Delphi would be the same:

 TThird = Class
 .....

TThird = Class(TObject)
 .....



IS operator

IS operator used to chech if an object reference to certain type, such as:

if (MyObject is TForm) then
....

as returns true if MyObject is a TForm object or any TForm descendant such as:

type
TMyForm = class (TForm)
....
var
MyForm: TMyForm;
Form1: TForm;
begin
MyForm:= TForm.Create(Self);
Form1:= TForm.Create(Self);
 if (MyForm is TForm) then...
if (Form1 is TForm) then....
if (Myform is TMyForm) then..
if (MyForm is TObject) then..


Above four if statements will return true.


AS operator

as operator used to typecast object to any desired object type such as:

MyObject as TButton

That mean we treat MyObject as a Button, for example we can access any button properties
and methods such as:

(MyObject as TButton).Caption:= 'E&xit';

Instead of using as operator we can explicty typecast objects using class type such
as:

TButton(MyObject).Caption:= 'E&xit';

Note:

Befor you typecast any object to another type make sure that the object reference
to desired object type or one of it's anscestors, if not; run-time error will be
generated. For example below statements are valid:

var
MyObject: TObject;
MyButton: TButton;
begin
MyObject:= Form1;
TForm(MyObject).WindowState:= wsMaximized;
(MyObject
as TForm).Caption:= 'Test';
MyObject:= Button1;
TButton(MyObject).Caption:= 'E&xit';
MyButton:= Button1;
(MyButton
as TObject).Name:= 'Button1';
end;

Below statements are invalid (appear in red color):

var
MyObject: TObject;
MyButton: TButton;
begin
MyObject:= Form1;
MyButton:= Button1;
 TForm(MyButton).Caption:= 'Invalid typecst';
(MyObject
as TButton).Caption:= 'Test';
end;


Example

1. Drop three Buttons, an Edit box, a Memo, and a ListBox.
2. Select all these components and double click at OnClick event for all of them,
(make sure that you write one event for all above component and share this event
for all componets)
3. At selected OnClick event write:

procedure TForm1.Button1Click(Sender: TObject);
begin
if Sender
is TButton then
  ShowMessage('This is a Button '+#10+
    (Sender
as TButton).Caption)
else
  if Sender
is TEdit then
  ShowMessage('This is an Edit box'+#10+
    (Sender
as TEdit).Text)
else
  if Sender
is TMemo then
  ShowMessage('This is a Memo'+#10+
    (Sender
as TMemo).Text)
else
  if Sender
is TCheckBox then
  ShowMessage('This is a CheckBox'+#10+
    (Sender
as TCheckBox).Caption);
end;


See also:

Creating components at run-time